#ifndef __BLOCKS_MANAGER_H__
#define __BLOCKS_MANAGER_H__

#include <vector>
#include <map>

#include "Blocks/Block.hpp"
#include "GameSingleton.h"

namespace PocketSurvival
{
    class BlocksManager : public SimpleSingletonItem
    {
        friend class SimpleSingleton;
    private:
        // 用于存放方块数据源的表
        std::map<std::string, std::vector<std::string>> m_blockDataMaps;

    private:
        BlocksManager();
        ~BlocksManager();
        BlocksManager(const BlocksManager &) = delete;
        BlocksManager(BlocksManager &&) = delete;
        BlocksManager &operator=(const BlocksManager &) = delete;
        BlocksManager &operator=(BlocksManager &&) = delete;

        void loadBlock(Block* block);

    public:
        void loadGame();

        /**
         * @brief 方块损坏，需要有耗损参数才有效
         * @param value 方块值，耗损次数
         * @note 若方块没有耗损的参数，那么耗损多少次都返回的都是原来的方块。
         * @return 耗损完后得新方块值,若耗损值降低到0，那么则会返回0
        */
        int32_t damageItem(int32_t value, int32_t damageCount);
        
        /**
         * @brief 加载方块数据源
         * @param blocksData 也就是 BlocksData.txt 的文本内容
        */
        void loadBlockSource(const std::string &blocksData);

        /**
         * @brief 清理掉内部缓存的方块数据源
        */
        inline void clearMap();

        /**
         * @brief 注册方块，注册好的方块就可在服务器中使用
         * @note 同样 id 的方块不可二次注册，不然会报错。一般来说，在插件 initialize 的时候调用该函数进行方块注册。
         *       若在 load 下，那么就使用到下面的 registerBlockAndLoad
        */
        template<class T>
        constexpr inline void registerBlock()
        {
            T* blockType = new T;
            blockType->addInheritance(blockType);
            loadBlock(blockType);
        }

        /**
         * @brief 注册方块并对方块进行初始化，注册好的方块就可在服务器中使用
         * @note 同样 id 的方块不可二次注册，不然会报错.
        */
        template<class T>
        constexpr inline void registerBlockAndLoad()
        {
            T* blockType = new T;
            blockType->addInheritance(blockType);
            loadBlock(blockType);
            blockType->initialize();
        }

    public:
        std::vector<Block *> blocks = std::vector<Block *>(1024, nullptr);

    };
    
    inline void BlocksManager::clearMap()
    {
        m_blockDataMaps.clear();
    }
} // namespace PocketSurvival

#endif